pub mod hook_t {
    use yew::{Callback, function_component, html, use_state};
    #[function_component(HookUseState)]
    pub fn state() -> Html {
        // statement the UseState Hook
        // hook takes a function as input which determines the initial state
        // used in the same across entire function lifecycle
        // change value : set(&self, new_value)
        // get the value: *(use_state)
        let counter = use_state(|| 0);
        let onclick = {
            let counter = counter.clone();
            Callback::from(move |_| counter.set(*counter + 1))
        };
        html!{
            <div>
                <button {onclick}>{"Increment val: "}</button>
                <p>
                    <b>{"cur value: "}</b>
                    {*counter}
                </p>
            </div>
        }
    }

    use web_sys::HtmlInputElement;
    use yew::{TargetCast, use_mut_ref};
    use yew::events::Event;

    #[function_component(HookUseMutRef)]
    pub fn mut_ref_hook() -> Html {
        // use_mut_ref is used to get a mutable reference to a value

        // use_state: String
        let message = use_state(|| "input message".to_owned());
        
        // use_mut_ref -> 0:i32
        let message_count = use_mut_ref(|| 0);

        // Button Event
        let onclick = Callback::from(move |_| {
            // for js like alert()
            let window = gloo_utils::window();
            // defer the reference and as a borrow_mut type value
            if *message_count.borrow_mut() > 3 {
                window.alert_with_message("Message limit reached").unwrap();
            } else {
                *message_count.borrow_mut() += 1;
                window.alert_with_message("Message sent").unwrap();
            }
        });
        // Input bar Event
        let onchange = {
            let message = message.clone();
            Callback::from(move |e: Event| {
                let input: HtmlInputElement = e.target_unchecked_into();
                // message: use_state
                message.set(input.value());
            })
        };
        html! {
            <div>
                <input {onchange} value={(*message).clone()}/>
                <button {onclick}>{"Send"}</button>
                <p>
                    <b style={"background-color: grey;"}>{format!("send times: {}", (*message).clone())}</b>
                </p>
            </div>
        }
    }
    use yew::functional::*;
    #[function_component(HookUseRef)]
    pub fn ref_hook() -> Html {
        // use_ref is used for get a immutable reference to a value
        // ref to the <input/>
        let input_ref = use_node_ref();
        let value = use_state(|| 0f64);
        let onclick = {
            let input_ref = input_ref.clone();
            let value = value.clone();
            move |_| {
                if let Some(input) = input_ref.cast::<HtmlInputElement>() {
                    value.set(*value + input.value_as_number());
                }
            }
        };
        html! {
            <div>
                <input type="number" ref={input_ref}/>
                <button {onclick}>{format!("Add input to {}", *value)}</button>
            </div>
        }
    }
    use std::rc::Rc;
    use yew::Reducible;
    enum CounterAction {
        Double,
        Square,
    }

    struct CounterState {
        counter: i32,
    }

    impl Default for CounterState {
        fn default() -> Self {
            Self { counter: 1 }
        }
    }

    impl Reducible for CounterState {
        type Action = CounterAction;

        fn reduce(self: Rc<Self>, action: Self::Action) -> Rc<Self> {
            let next_ctr = match action {
                CounterAction::Double => self.counter * 2,
                CounterAction::Square => self.counter + 1,
            };
            Self { counter: next_ctr }.into()
        }
    }

    #[function_component(HookUseReducer)]
    pub fn reducer() -> Html {
        let counter = use_reducer(CounterState::default);
        let double_onclick = {
            let counter = counter.clone();
            Callback::from(move |_| counter.dispatch(CounterAction::Double))
        };
        let square_onclick = {
            let counter = counter.clone();
            Callback::from(move |_| counter.dispatch(CounterAction::Square))
        };
        html! {
            <>
                <div id="result">{counter.counter}</div>
                <button onclick={double_onclick}>{"Double"}</button>
                <button onclick={square_onclick}>{"Square"}</button>
            </>
        }
    }

    #[function_component(HookUseEffect)]
    pub fn effect() -> Html {
        let counter = use_state(|| 0);
        {
            let counter = counter.clone();
            use_effect(move || {
                gloo_utils::document().set_title(&format!("You click {} times", *counter));
                || gloo_utils::document().set_title("You click 0 times")
            });
        }
        let onclick = {
            let counter = counter.clone();
            Callback::from(move |_| counter.set(*counter + 1))
        };
        html!{
            <button {onclick}>{format!("cur val: {}", *counter)}</button>
        }
    }

    use yew::{ContextProvider, use_context};
    #[derive(Clone, PartialEq, Debug)]
    pub struct Theme {
        foreground: String,
        background: String,
    }

    #[function_component(HookUseContext)]
    pub fn context() -> Html {
        let ctx = use_state(|| Theme {
             foreground: "#000000".to_owned(),
             background: "#eee1ee".to_owned()});
        html!{
            <ContextProvider<Theme> context={(*ctx).clone()}>
                <Toolbar/>
            </ContextProvider<Theme>>
        }
    }

    #[function_component(Toolbar)]
    pub fn toolbar() -> Html {
        html! {
            <div>
                <ThemeButton />
            </div>
        }
    }
    #[function_component(ThemeButton)]
    pub fn themed_button() -> Html {
        let theme = use_context::<Theme>().expect("no ctx found");
        html! {
            <button style={format!("background: {}; color: {};", theme.background, theme.foreground)}>
                {"click me"}
            </button>
        }
    }
}